package com.example.design.singletonDemo;

import java.io.Serializable;

/**
 * 懒汉式 线程安全写法
 * 优势 能够保证线程安全 ，但是在获取对象是每次都会处于阻塞状态 ，当对象已经创建好了 获取对象的时候不需要阻塞
 */
public class Singleton3 implements Serializable {

    private static Singleton3 singleton3;

    private Singleton3() throws Exception {
        synchronized (Singleton3.class) {
            if (singleton3 != null) {
                throw new Exception("已经被初始化了");
            }
            System.out.println("执行Singleton3无参构造函数...");
        }

    }

    public synchronized static Singleton3 getSingleton3() throws Exception {
        if (singleton3 == null) {
            Thread.sleep(2000);
            singleton3 = new Singleton3();
        }
        return singleton3;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                Singleton3 singleton2 = null;
                try {
                    singleton2 = Singleton3.getSingleton3();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "----------------" + singleton2);
            }).start();
        }
    }

    //返回序列化获取对象 ，保证为单例
    //在jdk中ObjectInputStream的类中有readUnshared（）方法，上面详细解释了原因。我简单描述一下，那就是如果被反序列化的对象的类存在readResolve这个方法，他会调用这个方法来返回一个“array”（我也不明白），然后浅拷贝一份，作为返回值，并且无视掉反序列化的值，即使那个字节码已经被解析
    public Object readResolve() {
        return singleton3;
    }
}
